#include "core/main.h"

int SpriteCollection::AddSprite(const Bitmap &bmp, const string &name, bool forceAdd)
{
    UINT64 hash = bmp.Hash64();
    const auto result = _spriteMap.find(hash);
    if(result == _spriteMap.end() || forceAdd)
    {
        SpriteEntry *newSprite = new SpriteEntry;
        newSprite->index = _spriteList.size();
        newSprite->bmp = bmp;
        newSprite->name = name;
        newSprite->transparent = (newSprite->bmp.CountPixelsWithColor(RGBColor::Magenta) > 0);

        const UINT indexHash = Utility::Hash32(newSprite->index);
        newSprite->visualizationColor = RGBColor(indexHash & 0xFF, (indexHash & 0xFF00) >> 8, (indexHash & 0xFF0000) >> 16);

        _spriteList.push_back(newSprite);
        _spriteMap[hash] = newSprite;
        return newSprite->index;
        //return *newSprite;
    }
    else
    {
        return result->second->index;
        //return *(result->second);
    }
}

Bitmap SpriteCollection::GetFontBitmap(char c) const
{
    string s;
    s += c;

    string filename = "../assets/common/font/" + s + ".png";

    if(Utility::FileExists(filename))
    {
        Bitmap result = Bitmap::LoadFile(filename);
        for(UINT y = 0; y < result.Height(); y++)
        {
            for(UINT x = 0; x < result.Width(); x++)
            {
                if(result[y][x] == result[0][0])
                {
                    if(x != 0 && y != 0) result[y][x] = RGBColor::Magenta;
                }
                else
                {
                    result[y][x] = RGBColor::White;
                }
            }
        }
        return result;
    }
    else if(c=='-')
    {
        Bitmap result = Bitmap::LoadFile("../assets/common/font/dash.png");
        for(UINT y = 0; y < result.Height(); y++)
        {
            for(UINT x = 0; x < result.Width(); x++)
            {
                if(result[y][x] == result[0][0])
                {
                    if(x != 0 && y != 0) result[y][x] = RGBColor::Magenta;
                }
                else
                {
                    result[y][x] = RGBColor::White;
                }
            }
        }
        return result;
    }
    else
    {
        return Bitmap::LoadFile("../assets/common/font/missingCharacter.png");
    }
}

void SpriteCollection::AddFontSprites()
{
    _fontBase = _spriteList.size();
    for(UINT numberIndex = 0; numberIndex < 10; numberIndex++)
    {
        AddSprite(GetFontBitmap('0' + numberIndex), "number-" + Utility::IntToString(numberIndex), true);
    }

    for(UINT letterIndex = 0; letterIndex < 26; letterIndex++)
    {
        AddSprite(GetFontBitmap('A' + letterIndex), "letter-" + Utility::IntToString(letterIndex), true);
    }

    AddSprite(GetFontBitmap('-'), "character--", true);
}

void SpriteCollection::DrawText(const string &message, const Vec2i &location, vector<SpriteLocation> &sprites, int spriteLayer) const
{
    for(UINT characterIndex = 0; characterIndex < message.size(); characterIndex++)
    {
        char c = message[characterIndex];
        if(c >= '0' && c <= '9')
        {
            sprites.push_back(SpriteLocation(Vec2i(Constants::NESTileSize * (location.x + characterIndex), Constants::NESTileSize * location.y), _fontBase + c - '0', spriteLayer));
        }
        else if(c >= 'A' && c <= 'Z')
        {
            sprites.push_back(SpriteLocation(Vec2i(Constants::NESTileSize * (location.x + characterIndex), Constants::NESTileSize * location.y), _fontBase + 10 + c- 'A', spriteLayer));
        }
        else if(c == '-')
        {
            sprites.push_back(SpriteLocation(Vec2i(Constants::NESTileSize * (location.x + characterIndex), Constants::NESTileSize * location.y), _fontBase + 36, spriteLayer));
        }
    }
}

void SpriteCollection::DrawNumber(int number, int zeroPadding, const Vec2i &location, vector<SpriteLocation> &sprites, int spriteLayer) const
{
    string s = Utility::ZeroPadInteger(number, zeroPadding);
    DrawText(s, location, sprites, spriteLayer);
}